package top.lyjwn.todo.aop.token.redis;

import com.alibaba.fastjson2.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import top.lyjwn.todo.aop.token.SubRedisJSONObject;
import top.lyjwn.todo.common.config.RedisConfig;

import jakarta.annotation.Resource;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Configuration
public class TokenRedis extends RedisConfig {

    private final Logger log = LoggerFactory.getLogger("error");

    @Resource(name = "tokenRedisTemplate")
    private RedisTemplate<String, JSONObject> redisTemplate;

    private Map<String, SubRedisJSONObject> subTokenMap = new ConcurrentHashMap<>();

    private int isRedisConfig = -1;

    private boolean IsRedisConfig() {
        if (isRedisConfig == -1) {
            String host = environment.getProperty("lyjwn.redis.host");
            String port = environment.getProperty("lyjwn.redis.port");
            isRedisConfig = (host == null || "".equals(host) || port == null || "".equals(port)) ? 0 : 1;
        }
        return isRedisConfig == 1;
    }

    /**
     * 过期时间
     *
     * @return
     */
    public long getExpireTime() {

        Long expire_time = 0L;
        try {
            expire_time = this.environment.getProperty("lyjwn.token.expire-time", Long.TYPE);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return expire_time == null ? 0 : expire_time;
    }

    /**
     * 是否jwt
     *
     * @return
     */
    public boolean IsJwt() {
        Boolean is_jwt = false;
        try {
            is_jwt = this.environment.getProperty("lyjwn.token.is_jwt", Boolean.TYPE);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return is_jwt == null ? false : is_jwt;
    }

    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                if (IsRedisConfig()) {
                    redisTemplate.expire(key, time, TimeUnit.MILLISECONDS);
                } else {
                    subTokenMap.get(key).setExpire(time);
                }
            }
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;

        }
    }

    public long getExpire(String key) {
        if (IsRedisConfig()) {
            return redisTemplate.getExpire(key, TimeUnit.MILLISECONDS);
        } else {
            return subTokenMap.get(key).getExpire();
        }
    }


    public boolean hasKey(String key) {
        try {
            if (IsRedisConfig()) {
                return redisTemplate.hasKey(key);
            } else {
                return subTokenMap.get(key) != null;
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }

    }

    public void delete(String... key) {
        if (key != null && key.length > 0) {
            if (IsRedisConfig()) {
                if (key.length == 1) {
                    redisTemplate.delete(key[0]);
                } else {
                    Collection<String> objects = Arrays.asList(key);
                    redisTemplate.delete(objects);
                }
            } else {
                for (String s : key) {
                    subTokenMap.remove(s);
                }
            }

        }

    }

    public boolean set(String key, JSONObject value) {
        long expireTime = this.getExpireTime();
        if (expireTime == 0) {
            try {
                if (IsRedisConfig()) {
                    redisTemplate.opsForValue().set(key, value);
                } else {
                    SubRedisJSONObject subRedisJSONObject = new SubRedisJSONObject();
                    subRedisJSONObject.setJSONObject(value);
                    subRedisJSONObject.setExpire(getExpireTime());
                    subRedisJSONObject.setWriteTime(new Date().getTime());
                    subTokenMap.put(key, subRedisJSONObject);
                }
                return true;
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return false;
            }
        } else {
            boolean res = set(key, value, expireTime);
            return res;
        }

    }

    public boolean set(String key, JSONObject value, long time) {
        try {
            if (time > 0) {
                if (IsRedisConfig()) {
                    redisTemplate.opsForValue().set(key, value, time, TimeUnit.MILLISECONDS);
                } else {
                    SubRedisJSONObject subRedisJSONObject = new SubRedisJSONObject();
                    subRedisJSONObject.setJSONObject(value);
                    subRedisJSONObject.setExpire(getExpireTime());
                    subRedisJSONObject.setWriteTime(time);
                    subTokenMap.put(key, subRedisJSONObject);
                }
                return true;
            } else {
                return set(key, value);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return false;
        }

    }

    public JSONObject get(String key) {
        if (IsRedisConfig()) {
            return key == null ? null : redisTemplate.opsForValue().get(key);
        } else {
            SubRedisJSONObject subRedisJSONObject = subTokenMap.get(key);
            if (subRedisJSONObject != null && (subRedisJSONObject.getWriteTime() + subRedisJSONObject.getExpire() >= new Date().getTime() || subRedisJSONObject.getExpire() == 0)) {
                return subRedisJSONObject.getJSONObject();
            }
            if (subRedisJSONObject != null && subRedisJSONObject.getWriteTime() + subRedisJSONObject.getExpire() < new Date().getTime()) {
                subTokenMap.remove(key);
            }
            return null;
        }
    }
}
